﻿

using System.IO;
using System.Xml.Linq;
using System.Linq;

namespace SSS.AlphaNN.Components
{
    using System.Collections.Generic;
    using System.Data.OleDb;
    using System;

    /// <summary>
    /// Тип файла для выходного сигнала
    /// </summary>
     [Flags]
    public enum TypeFileInput:int
    {
        CSV=0x0,
        XML=0x1,
        Access=0x10
    }

    public partial class Sink 
    {
        #region Properties
        /// <summary>
        /// Дата и время выполнения расчетов сети. 
        /// Для добавления к названию таблицы, поэтому string
        /// </summary>
        public string DateAndTime
        {
            get;
            set;
        }

        /// <summary>
        /// Тип файла для выходного сигнала
        /// </summary>
        public TypeFileInput typeFileInput
        {
            get; set;
        }

        #endregion

        /// <summary>
        /// Метод для сохранения в XML файл
        /// </summary>
        /// <param name="liOutput">Выходной сигнал</param>
        private void SaveDataInXMLFile(List<List<double>> liOutput)
        {
            
            XElement xel = new XElement("DataOutput",
                new XElement("Rows",
                    liOutput.Select(x => 
                        new XElement("row",
                        new XElement("columns", 
                                     x.Select(y => 
                                         new XElement("column", y)))))));
            XDocument xdoc = new XDocument(xel);
            xdoc.Save(PathFileDb);
        }

        /// <summary>
        /// Метод для сохранения в файл CSV
        /// </summary>
        /// <param name="liOutput">Выходной сигнал</param>
        private void SaveDataInCSV(List<List<double>> liOutput)
        {
            StreamWriter sw=new StreamWriter(PathFileDb);

            string str = "";

            liOutput.ForEach(x =>
                                 {
                                     x.ForEach(y =>
                                                   {
                                                       str += y.ToString() + ";";
                                                   });
                                     str = str.TrimEnd(';');
                                     str += "\r\n";
                                     sw.Write(str);
                                     sw.Flush();
                                     str = "";
                                 });
            sw.Close();
        }

        /// <summary>
        /// Сохранение в базу данных Access
        /// </summary>
        /// <param name="liOutput">Выходной сигнал</param>
        private void SaveDataInAccess(List<List<double>> liOutput)
        {
            if (liOutput.Count == 0)
                return;

            //Login = "Admin"; Администратор у него это Admin. Пользователь не устанавливается в БД, только пароль.
            //Если что, то можно User ID= {2}; убрать, как пишут в интернете
            //Password = "123";

            string dateDB = DateTime.Now.ToShortDateString();
            string Date = string.Empty;

            for (int i = 0; i < dateDB.Length; i++)
                if (dateDB.Substring(i, 1) == ".")
                    Date += ":";
                else
                    Date += dateDB.Substring(i, 1);

            string tableName = "Output_" + Date + "_" + DateTime.Now.ToLongTimeString();

            OleDbConnection oleDataBaseConnection = null;

            try
            {
                string provider = string.Empty;
                if (PathFileDb.Contains(".accdb"))
                {
                    provider = "Microsoft.ACE.OLEDB.12.0";
                }
                else
                {
                    provider = "Microsoft.ACE.OLEDB.11.0";
                }

                //Можно передать что угодно, хоть пароль, даже если он не установлен. И пустую учетку можно передать,
                //если База данных используется как проходной двор
                oleDataBaseConnection = new OleDbConnection(string.Format(@"Provider={0}; Data Source={1}; 
                        User ID= {2}; Jet OLEDB:Database Password= {3}",
                    provider, PathFileDb, Login, Password));

                oleDataBaseConnection.Open();

                OleDbCommand sqlInCommand;

                string insertingString = string.Empty;
                string createString = "Create table " + tableName + "(";

                for (int i = 0; i < liOutput[0].Count; i++)
                {
                    createString += "val" + i.ToString() + " decimal ,";
                }

                //Создаем таблицу всегда, от даты и времени =)
                createString = createString.Remove(createString.Length - 1);
                createString += ")";

                sqlInCommand = new OleDbCommand(createString, oleDataBaseConnection);
                sqlInCommand.ExecuteNonQuery();

                foreach (List<double> line in liOutput)
                {
                    insertingString = string.Empty;

                    for (int i = 0; i < line.Count; i++)
                    {
                        insertingString += line[i] + ",";
                    }

                    insertingString = insertingString.Remove(insertingString.Length - 1);
                    string insertQuery = string.Format("Insert into {0} values ({1})", tableName, insertingString);
                    
                    sqlInCommand = new OleDbCommand(insertQuery, oleDataBaseConnection);
                    sqlInCommand.ExecuteNonQuery();
                }
            }
            catch
            { 
                //тут типа ничего не произойдет в случае ошибки
            }
            finally
            {
                if (oleDataBaseConnection.State == System.Data.ConnectionState.Open)
                    oleDataBaseConnection.Close();
            }
        }

        /// <summary>
        /// Сохранение данных
        /// </summary>
        /// <param name="liOuptut">Выходной сигнал</param>
        public void SaveData(List<List<double>> liOuptut)
        {
            switch (typeFileInput)
            {
                case TypeFileInput.Access:
                    SaveDataInAccess(liOuptut);
                    break;
                case TypeFileInput.CSV:
                    SaveDataInCSV(liOuptut);
                    break;
                case TypeFileInput.XML:
                    SaveDataInXMLFile(liOuptut);
                    break;
                default:
                    break;
            }
        }
    }
}
